#include "ina226.h"
#include "sys.h"
#include "delay.h"

INA226 ina226_data;

void INA226_Init()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能时钟

	//SDA:PA11   SCL:PA12 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//开漏输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	INA226_SendData(INA226_ADDR1,CFG_REG,0x8000);	//重新启动,让所有寄存器重置为默认值
	
	INA226_SendData(INA226_ADDR1,CFG_REG,0x4727);	//设置转换时间1.1ms,求平均值次数64,总耗时=平均次数*(分流电压转换时间+总线电压转换时间)设置模式为分流和总线连续模式
	INA226_SendData(INA226_ADDR1,CAL_REG,CAL);	//设置分辨率
	
}
void INA226_I2C_SDA_OUT()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//开漏输出
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}


void INA226_I2C_SDA_IN()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void INA226_I2C_Start()
{
	INA226_I2C_SDA_OUT();
	INA226_I2C_SCL=1;
	INA226_I2C_SDA=1;
	delay_us(5);
	INA226_I2C_SDA=0;
	delay_us(5);
	INA226_I2C_SCL=0;
	delay_us(5);
}


void INA226_I2C_Stop()
{
	INA226_I2C_SDA_OUT();
	INA226_I2C_SCL=0;
	INA226_I2C_SDA=0;
	delay_us(5);
	INA226_I2C_SCL=1;
	delay_us(5);
	INA226_I2C_SDA=1;
	delay_us(5);
}

//产生应答信号：0
void INA226_I2C_Ack()
{
	INA226_I2C_SDA_OUT();
	INA226_I2C_SCL=0;
	INA226_I2C_SDA=0;
	delay_us(5);
	INA226_I2C_SCL=1;
	delay_us(5);
	INA226_I2C_SCL=0;
}

//产生非应答信号：1
void INA226_I2C_NAck()
{
	INA226_I2C_SDA_OUT();
	INA226_I2C_SCL=0;
	INA226_I2C_SDA=1;
	delay_us(5);
	INA226_I2C_SCL=1;
	delay_us(5);
	INA226_I2C_SCL=0;
}


uint8_t INA226_I2C_Wait_Ack()
{
		uint8_t ucErrTime=0;
		INA226_I2C_SDA_IN();
    INA226_I2C_SDA=1;
		delay_us(5);       
    INA226_I2C_SCL=1;
		delay_us(5);     
    while(I2C_SDA_READ)
    {
        ucErrTime++;
        if(ucErrTime>250)
        {
            INA226_I2C_Stop();
            return 1;
        }
    }
    INA226_I2C_SCL=0;       
    return 0;  
}
void INA226_I2C_Send_Byte(uint8_t Byte)
{
		uint8_t t;       
		INA226_I2C_SDA_OUT();	
    INA226_I2C_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        INA226_I2C_SDA=(Byte&0x80)>>7;//把最高位右移到最低位并发送出去
				Byte<<=1;//左移1位，把原先的最高位下一位成为最高位，为重复上一步操作做准备
        delay_us(5);   
        INA226_I2C_SCL=1;
        delay_us(5); 
        INA226_I2C_SCL=0;    
        delay_us(5);
    }     
	
}


uint8_t INA226_I2C_Read_Byte(uint8_t ack)
{
		uint8_t i,receive=0;
		INA226_I2C_SDA_IN();
    for(i=0;i<8;i++ )
    {
        INA226_I2C_SCL=0; 
        delay_us(5);
        INA226_I2C_SCL=1;
				receive<<=1;//左移1位，接收后续数据
        if(I2C_SDA_READ)
				{
					receive+=1; 
				}	
        delay_us(5); 
    }                     
    if (!ack)
        INA226_I2C_NAck();//发送nACK
    else
        INA226_I2C_Ack(); //发送ACK   
    return receive;
}
//////////////////////////////////////
//addr: 从机地址,0x80
// reg: 寄存器指针地址
void INA226_SetRegPointer(u8 addr,u8 reg)
{
	INA226_I2C_Start();
 
	INA226_I2C_Send_Byte(addr);
	INA226_I2C_Wait_Ack();
 
	INA226_I2C_Send_Byte(reg);
	INA226_I2C_Wait_Ack();
	
	INA226_I2C_Stop();
}


//发送,写入数据
void INA226_SendData(u8 addr,u8 reg,u16 data)
{
	u8 temp=0;
	INA226_I2C_Start();
 
	INA226_I2C_Send_Byte(addr);
	INA226_I2C_Wait_Ack();
 
	INA226_I2C_Send_Byte(reg);
	INA226_I2C_Wait_Ack();
	
	temp = (u8)(data>>8);
	INA226_I2C_Send_Byte(temp);
	INA226_I2C_Wait_Ack();
 
	temp = (u8)(data&0x00FF);
	INA226_I2C_Send_Byte(temp);
	INA226_I2C_Wait_Ack();
	
	INA226_I2C_Stop();
}
 
//读取数据
u16 INA226_ReadData(u8 addr)
{
	u16 temp=0;
	INA226_I2C_Start();
 
	INA226_I2C_Send_Byte(addr+1);
	INA226_I2C_Wait_Ack();
	
	temp = INA226_I2C_Read_Byte(1);
	temp<<=8;	
	temp |= INA226_I2C_Read_Byte(0);
	
	INA226_I2C_Stop();
	return temp;
}
//1mA/bit
u16 INA226_GetShunt_Current(u8 addr)
{
	u16 temp=0;	
	INA226_SetRegPointer(addr,CUR_REG);
	temp = INA226_ReadData(addr);
	if(temp&0x8000)	temp = ~(temp - 1);	
	return temp;
}
 
////获取id
//void INA226_Get_ID(u8 addr)
//{
//	u32 temp=0;
//	INA226_SetRegPointer(addr,INA226_GET_ADDR);
//	temp = INA226_ReadData(addr);
//	ina226_data.ina226_id = temp;
//}
 
//获取校准值
u16 INA226_GET_CAL_REG(u8 addr)
{	
	u32 temp=0;
	INA226_SetRegPointer(addr,CAL_REG);
	temp = INA226_ReadData(addr);
	return (u16)temp;
}
 
//1.25mV/bit
u16 INA226_GetVoltage(u8 addr)
{
	u32 temp = 0;
	INA226_SetRegPointer(addr,BV_REG);
	temp = INA226_ReadData(addr);
	return (u16)temp;	
}
 
//2.5uV/bit
u16 INA226_GetShuntVoltage(u8 addr)
{
	int16_t temp = 0;
	INA226_SetRegPointer(addr,SV_REG);
	temp = INA226_ReadData(addr);
	if(temp&0x8000)	temp = ~(temp - 1);	
	return (u16)temp;	
}
 
//获取电压
void GetVoltage(float *Voltage)//mV
{
	*Voltage = INA226_GetVoltage(INA226_ADDR1)*Voltage_LSB;
}
 
//获取分流电压
void Get_Shunt_voltage(float *Voltage)//uV
{
	*Voltage = (INA226_GetShuntVoltage(INA226_ADDR1)*INA226_VAL_LSB);//如需矫正电流分流参数请将这里改为2.5
}
 
//获取电流
void Get_Shunt_Current(float *Current)//mA
{
	*Current = (INA226_GetShunt_Current(INA226_ADDR1)* CURRENT_LSB);
}
 
//获取功率= 总线电压 * 电流
void get_power()//mW
{
	GetVoltage(&ina226_data.voltageVal);			//mV
	Get_Shunt_voltage(&ina226_data.Shunt_voltage);	//uV
	Get_Shunt_Current(&ina226_data.Shunt_Current);	//mA
	Get_Power(&ina226_data.Power);
	ina226_data.PowerVal = ina226_data.voltageVal* ina226_data.Shunt_Current; 	//mV*mA
}
 
//获取功率装载值,ina226内部计算的的功率，由于未经校准，故不采用
 
u16 INA226_Get_Power(u8 addr)
{
	int16_t temp=0;
	INA226_SetRegPointer(addr,PWR_REG);
	temp = INA226_ReadData(addr);
	return (u16)temp;
}
 
//获取功率,ina226内部计算，不准确，不采用
void Get_Power(float *Power)//W
{
	*Power = (INA226_Get_Power(INA226_ADDR1)*POWER_LSB);
}
